package org.jwebuilder.event;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.text.MessageFormat;

import org.jwebuilder.annotations.events.AfterRender;
import org.jwebuilder.annotations.events.BeforeRender;
import org.jwebuilder.annotations.events.EventHandler;
import org.jwebuilder.event.EventResult.ResultType;

public class EventUtils
{
	public static final String EVENT_HANDLER_PARAMETER_NAME = "_JWebuilder_EventHandler_";
	public static final String EVENT_HANDLER_PARAMETER_VALUE_PREFIX = "EventHandler:";

	public static Object fireBeforeRender(Object listener)
	{
		return fireEvent(BeforeRender.class, listener);
	}
	
	public static Object fireAfterRender(Object listener)
	{
		return fireEvent(AfterRender.class, listener);
	}
	
	/**
	 * 调用指定事件监听器中与特定事件相关的所有处理器方法
	 * @param event 特定事件
	 * @param listener 事件监听器
	 * @return
	 * @throws EventException
	 */
	public static Object fireEvent(Class<? extends Annotation> event, Object listener) throws EventException
	{
		if(event.getAnnotation(EventHandler.class) == null)
		{
			throw new EventException(MessageFormat.format("{0} is not a valid event of JWebuilder.", event.getCanonicalName()));
		}
		
		Method[] methods = listener.getClass().getMethods();
		Object result = null;
		EventResult eventResult = null;
		for(Method method : methods)
		{
			if(method.getAnnotation(event) != null)
			{
				try
				{
					result = method.invoke(listener, new Object[0]);
					if(result != null && result.getClass() == EventResult.class)
					{
						eventResult = (EventResult) result;
						if(eventResult.getResultType() == ResultType.BreakChain)
						{
							result = null;
							break;
						}
						else if(eventResult.getResultType() == ResultType.ForceRedirect || eventResult.getResultType() == ResultType.ForceForward)
						{
							break;
						}
					}
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}
		return result;
	}
	
	/**
	 * 调用指定事件监听器中指定的事件处理器方法
	 * @param eventHandleMethodName 事件处理器方法名称
	 * @param listener 事件监听器
	 * @return
	 */
	public static Object invokeEventHandler(String eventHandleMethodName, Object listener)
	{
		Object result = null;
		EventResult eventResult = null;
		try
		{
			Method method = listener.getClass().getMethod(eventHandleMethodName, new Class[0]);
			result = method.invoke(listener, new Object[0]);
			if(result != null && result.getClass() == EventResult.class)
			{
				eventResult = (EventResult) result;
				if(eventResult.getResultType() == ResultType.BreakChain)
				{
					result = null;
				}
			}
		}
		catch (Exception e)
		{
			e.printStackTrace();
		}
		return result;
	}
}